##########################################################################
#  Copyright (C) 2007 Robert Connolly <rob_connolly@mailshack.com>       #
#                                                                        #
#  This program is free software; you can redistribute it and/or modify  #
#  it under the terms of the GNU General Public License as published by  #
#  the Free Software Foundation; either version 3 of the License, or     #
#  (at your option) any later version. See file COPYING for details.     #
#                                                                        #
#  This program is distributed in the hope that it will be useful,       #
#  but WITHOUT ANY WARRANTY; without even the implied warranty of        #
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         #
#  GNU General Public License for more details.                          #
#                                                                        #
#  You should have received a copy of the GNU General Public License     #
#  along with this program; if not, write to the                         #
#  Free Software Foundation, Inc.,                                       #
#  59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             #
##########################################################################

__all__ = ['Display', 'Sensor']

import gobject, gtk, gconf
import cairo
import threading, thread
import time

class Display(gtk.Window):
	__gsignals__ = {'daemon-quit' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()),
			'display-quit' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_STRING,))}

	def __init__(self, name, has_prefs=False):
		self.dname = name
		
		self.client = gconf.client_get_default()
		self.client.add_dir('/apps/cairolets/displays/%s' % self.dname, gconf.CLIENT_PRELOAD_NONE)
	
		gtk.Window.__init__(self)
		
		self.set_property("skip-taskbar-hint", True)
		self.stick()
		self.set_title("Cairolets: %s" % self.dname)
		
		self.set_app_paintable(True)
		self.set_decorated(False)
		
		x_pos = self.client.get_int("/apps/cairolets/displays/%s/x_pos" % self.dname)
		y_pos = self.client.get_int("/apps/cairolets/displays/%s/y_pos" % self.dname)
		self.move(x_pos, y_pos)
		
		self.connect("delete-event", self.quit)
		self.connect("expose_event", self.__expose)
		
		manager = gtk.UIManager()
		
		action1 = gtk.Action('Kill', 'Kill', "Stop this Desklet", 'gtk-stop')
		action1.connect('activate', lambda a: self.quit())
		
		action2 = gtk.Action('Preferences', 'Preferences', "Edit Desklet Preferences", 'gtk-preferences')
		action2.connect('activate', lambda a: self.do_prefs_dialog())
		if has_prefs == False:
			action2.set_property('sensitive', False)
		
		action3 = gtk.Action('EditSkin', 'Edit Skin', "Edit this Desklet's Skin", 'gtk-properties')
		#action3.connect('activate', lambda a: self.delete_thyself())
		action3.set_property('sensitive', False)
		
		action4 = gtk.Action('Browser', 'Desklet Browser', "Browse Availiable Desklets", '')
		#action1.connect('activate', lambda a: self.delete_thyself())
		action4.set_property('sensitive', False)
		
		action5 = gtk.Action('Quit', 'Quit', "Exit Cairolets", 'gtk-quit')
		action5.connect('activate', lambda a: self.emit('daemon-quit'))
		
		action_group = gtk.ActionGroup('NJBPluginActions')
		action_group.add_action(action1)
		action_group.add_action(action2)
		action_group.add_action(action3)
		action_group.add_action(action4)
		action_group.add_action(action5)
		manager.insert_action_group(action_group, 0)
		
		self.__ui = manager.add_ui_from_file("gui/right-click-popup.xml")
		manager.ensure_update()
		self.__popup = manager.get_widget("/DeskletPopup")
		
		self.add_events(gtk.gdk.BUTTON_PRESS_MASK)
		self.connect("event", self.__event)
		
	def __expose(self, widget, event):
	
		(self.width, self.height) = widget.get_size()
		
		ctx = widget.window.cairo_create()
		
		ctx.set_source_rgba(1.0, 1.0, 1.0, 0.0)
		ctx.set_operator(cairo.OPERATOR_SOURCE)
		ctx.paint()
		
		self.do_expose(ctx)
		
		pix = gtk.gdk.Pixmap(None, self.width, self.height, 1)
    		self.mask = pix.cairo_create()
    		
    		self.do_window_mask()
    		
    		self.mask.fill()
    		self.mask.stroke()
    		self.input_shape_combine_mask(pix, 0, 0)
		
	def __event(self, widget, event):
		if event.type == gtk.gdk.BUTTON_PRESS:
			if event.button == 3:
				self.__popup.popup(None, None, None, event.button, event.time)
		
	def quit(self):
		(x_pos, y_pos) = self.get_position()
		self.client.set_int("/apps/cairolets/displays/%s/x_pos" % self.dname, x_pos)
		self.client.set_int("/apps/cairolets/displays/%s/y_pos" % self.dname, y_pos)
		self.emit("display-quit", self.dname)
		self.destroy()
		self.do_quit()
	
	def run(self):
		screen = self.get_screen()
		colourmap = screen.get_rgba_colormap()
		
		if colourmap == None:
			print "ERROR: Your display does not support transparency!"
			return False
		
		self.set_colormap(colourmap)
	
		self.show_all()
		
	def do_expose(self, ctx):
		pass
		
	def do_window_mask(self):
		pass
		
	def do_prefs_dialog(self):
		pass
		
	def do_quit(self):
		pass

class Sensor(gobject.GObject):
	__gsignals__ = {'data-changed' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_STRING,))}

	__data = dict()
	__killed = False
	
	def __init__(self, init_data=None, async=True, delay=1):
		gobject.GObject.__init__(self)
		if init_data != None:
			self.__data = init_data
		if async == True:
			self.__delay = delay
			#gtk.gdk.threads_init()
			self.__thread = threading.Thread(target=self.__thread)
			self.__thread.start()
	
	def do_step(self):
		return False
			
	def __thread(self):
		while True:
			if self.__killed == True:
				thread.exit()
			elif self.do_step() == False:
				thread.exit()
			else:
				time.sleep(self.__delay)
				
	def get_data(self, key=None):
		if key != None:
			return self.__data[key]
		else:
			return self.__data
		
	def edit_data(self, key, value):
		if key in self.__data:
			if value != self.__data[key]:
				self.__data[key] = value
				self.emit('data-changed', key)
		else:
			self.__data[key] = value
			self.emit('data-changed', key)
			
	def set_data(self, data):
		self.__data = data
		self.emit('data-changed', 'all')
	
	def kill(self):
		self.__killed = True
	
